Add wasm32-unknown-emscripten target support#2805
Draft
guybedford wants to merge 2 commits into
Draft
Conversation
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the full test suite under Node. Source changes to compile on emscripten (which behaves like a Linux/musl libc): * ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten (src/sys/ioctl, src/sys/mod.rs). * resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit. * socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed) decode arms. * unistd: sethostname is unavailable on emscripten, so gate it out. The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and sockets with node's. This needs nightly + rust-src and a JSPI-capable Node (26+, or 22 with --experimental-wasm-jspi). No custom target spec is required: nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937). Genuinely-unsupported operations are ignored with #[cfg_attr(target_os = "emscripten", ignore)] rather than cfg'd out, covering fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex, pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, thread signal masking, and setrlimit; a few tests are cfg'd out where the feature is entirely absent (raw signal actions, socketpair) or the host differs (linkat symlink follow). Temporary, until the dependencies land upstream: * Cargo.toml patches libc to guybedford/libc#libc-0.2-emscripten for the emscripten externs (rust-lang/libc#5270). * the CI job builds against the guybedford/emscripten `cf` fork, which carries the NODEFS/socket/blocking patches this target depends on (emscripten-core/emscripten#27305, #27306). Suite result: 148 passed, 0 failed, 35 ignored under Node - green on Linux CI.
199bda8 to
cb64cba
Compare
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the full test suite under Node. Source changes to compile on emscripten (which behaves like a Linux/musl libc): * ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten (src/sys/ioctl, src/sys/mod.rs). * resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit. * socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed) decode arms. * unistd: sethostname is unavailable on emscripten, so gate it out. The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and sockets with node's. This needs nightly + rust-src and a JSPI-capable Node (26+, or 22 with --experimental-wasm-jspi). No custom target spec is required: nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937). Unsupported operations are ignored with #[cfg_attr(target_os = "emscripten", ignore)] rather than cfg'd out wherever they still compile, covering fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex, pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, getsockname, socketpair, setrlimit, and the linkat symlink-follow host check. The signal-delivery tests (signal, killpg, thread mask) and the AF_ROUTE test are cfg'd out instead: compiling their extern "C" handlers in perturbs the wasm indirect function table and aborts the runtime. Temporary, until the dependencies land upstream: * the emscripten CI job injects a libc patch (guybedford/libc#libc-0.2-emscripten, rust-lang/libc#5270) via `cargo --config`, so other targets and CI jobs are unaffected. * it also builds against the guybedford/emscripten `cf` fork, which carries the NODEFS/socket/blocking patches this target depends on (emscripten-core/emscripten#27305, #27306). Suite result: 148 passed, 0 failed, 38 ignored under Node - green on Linux CI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR for #2804.
Adds
wasm32-unknown-emscriptenas a target for nix, with a CI job running the full test suite under Node (stock target,-Zbuild-stdthreaded, JSPI, NODERAWFS/NODERAWSOCKETS). Opened as a draft since it depends on unreleased patchsets for both Emscripten and Rust's libc, including:Requires a recent Rust nightly to include rust-lang/rust#158937.
Test Status
148 passing, 38 ignored at runtime, 5 compiled out.
Ignored (38):
test_unistd(11): test_fork_and_waitpid, test_wait, test_mkfifo, test_mkfifoat, test_mkfifoat_none, test_setgroups, test_acct, test_pipe2, test_user_into_passwd, test_ttyname, test_linkat_no_follow_symlinktest_pty(6): test_open_ptty_pair, test_read_ptty_pair, test_write_ptty_pair, test_openpty, test_openpty_with_termios, test_forkptytest_socket(7): recvfrom::stream, test_recvmsg_sockaddr_un, test_scm_rights, test_scm_rights_single_cmsg_multiple_fds, test_sendmsg_empty_cmsgs, test_getsockname, test_socketpairtest_termios(3): test_tcgetattr_pty, test_output_flags, test_local_flagstest_wait(3): test_wait_signal, test_wait_exit, test_waitstatus_pidtest_fcntlflock (3): lock_and_drop, downgrade, upgradetest_net(2): test_if_nametoindex, test_if_indextonametest_resource(1): test_resource_limits_nofiletest_signal(1): test_thread_signal_swaptest_sockopt(1): is_socket_type_unixCompiled out (5):
test_socket(1): can_open_routing_sockettest_signal(4): test_killpg_none, test_signal, test_thread_signal_set_mask, test_thread_signal_blockEarly feedback on the approach very much welcome.